<?php
/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: dzf_base_router.php 1911 2013-08-26 02:26:48Z laoguozhang $
 */

if(!defined('IN_DISCUZ')) {
	exit('Access Denied');
} 

class dzf_base_router extends dzf_base_class
{
	public $default_controller = 'index';
	public $default_action = 'index';
	public $controller = '';
	public $action = '';

	protected $_rules = array();				// 规则
	protected $_routes = array();				// 路由器对象集合

	
	
	protected function _isValidRule($rule) {
		if (!is_string($rule[0])) {
			return false;
		}
	
		if (!is_array($rule[2]) || !$rule[2]) {
			return false;
		}
	    
		return true;
	}
	
	public function __construct($rules = array()) {
		$this->_rules = $rules;
	
		if ($rules) {
			
			foreach ($rules as $rule) {
				if ($this->_isValidRule($rule)) {
					array_push($this->_routes, new dzf_base_controller_router($rule[0], $rule[1], $rule[2]));
				}
			}
		}
		
		
	}
	
	public function parse($request) {
		$match = $request->getPathInfo();
		
		foreach ($this->_routes as $route) {
			if ($params = $route->match($match)) {
				break;
			}
		}
		foreach($params as $key => $param) {
			$_GET[$key] = $param;
		}
		$this->controller = isset($_GET['c']) && !empty($_GET['c']) && ctype_alnum($_GET['c']) ? $_GET['c'] : $this->default_controller;
		$this->action = isset($_GET['a']) && !empty($_GET['a']) && ctype_alnum($_GET['a']) ? $_GET['a'] : $this->default_action;
	}
}

class dzf_base_controller_router 
{
	protected $_urlVariable = ':';				// 变量标示符
	protected $_urlDelimiter = '/';				// url分隔符
	protected $_regexDelimiter = '#';			// 正则表达式分界符
	protected $_defaultRegex = null;            // 默认正则
	protected $_variables = array();			// 变量
	protected $_parts = array();				// 需要匹配部分
	protected $_defaults = array();				// 默认值
	protected $_requirements = array();			// 变量对应的正则
	protected $_values = array();				// 匹配完成的部分
	protected $_wildcardData = array();			// 通配符匹配部分
	protected $_staticCount = 0;				// 非变量匹配次数统计
	
	public function __construct($route, $reqs = array(), $defaults = array()) {
	
		$route               = trim($route, $this->_urlDelimiter);
		$this->_defaults     = (array) $defaults;
		$this->_requirements = (array) $reqs;
		
		if ($route !== '') {
			foreach (explode($this->_urlDelimiter, $route) as $pos => $part) {
				if (substr($part, 0, 1) == $this->_urlVariable && substr($part, 1, 1) != $this->_urlVariable) {
	
					// 以:开头的,规则变量名
					$name = substr($part, 1);
					
					// pattern放入_parts中
					if (isset($reqs[$name])) {
						$this->_parts[$pos] = $reqs[$name];
					} else {
						$this->_parts[$pos] = $this->_defaultRegex;
					}
	
					// 变量放入_variables组中
					$this->_variables[$pos] = $name;
				} else {
	
					// pattern都放在_parts中
					$this->_parts[$pos] = $part;
	
					if ($part !== '*') {
						$this->_staticCount++;
					}
				}
			}
		}
	}
	
	public function match($path) {
	    
		$pathStaticCount = 0;
		$values          = array();
		$matchedPath     = '';
	
		$path = trim($path, $this->_urlDelimiter);
		
		if($path === '') {
		    return false;
		}
		$path = explode($this->_urlDelimiter, $path);
		foreach ($path as $pos => $pathPart) {
			if (!array_key_exists($pos, $this->_parts)) {
				return false;
			}
            
			$matchedPath .= $pathPart . $this->_urlDelimiter;

			// 如果是通配符，则直接匹配所有剩余的部分，并退出
			if ($this->_parts[$pos] == '*') {
				$count = count($path);
				for($i = $pos; $i < $count; $i+=2) {
					$var = urldecode($path[$i]);
					if (!isset($this->_wildcardData[$var]) && !isset($this->_defaults[$var]) && !isset($values[$var])) {
						if (isset($path[$i+1])) {
							$this->_wildcardData[$var] = urldecode($path[$i+1]);
						} else {
							$this->_wildcardData[$var] = null;
						}
					}
				}

				$matchedPath = implode($this->_urlDelimiter, $path);
				break;
			}
            
			if (isset($this->_variables[$pos])) {
				$name = $this->_variables[$pos];
			} else {
				$name = null;
			}

			$pathPart = urldecode($pathPart);

			$part = $this->_parts[$pos];

			// 对于不是变量的，直接匹配即可
			if ($name === null && $part != $pathPart) {
				return false;
			}

			// 如果是变量，使用正则匹配
			if ($part !== null && !preg_match($this->_regexDelimiter . '^' . $part . '$' . $this->_regexDelimiter . 'iu', $pathPart)) {
				return false;
			}

			// 将匹配上的变量放入$values数组
			if ($name !== null) {
				$values[$name] = $pathPart;
			} else {
				// 统计非变量个数
				$pathStaticCount++;
			}

		}
       
		// 检查非变量匹配正确性
		if ($this->_staticCount != $pathStaticCount) {
			return false;
		}

		$return = $values + $this->_wildcardData + $this->_defaults;

		// 检查一下，是不是所有的变量都匹配了
// 		foreach ($this->_variables as $var) {
// 			if (!array_key_exists($var, $return)) {
// 				return false;
// 			}
// 		}

		$this->_values = $values;

		return $return;
	}
}



